/*******************************************************************************
 * $Header: /home/cvsroot/develop/workspace/base/com.ease.java/src/com/ease/tp/i18n/ResourceMessageUtil.java,v 1.1 2012/09/26 16:17:27 liwei Exp $
 * $Revision: 1.1 $
 * $Date: 2012/09/26 16:17:27 $
 *
 *==============================================================================
 *
 * Copyright (c) 2001-2006 Primeton Technologies, Ltd.
 * All rights reserved.
 *
 * Created on 2007-12-24
 *******************************************************************************/

package com.ease.context.i18n;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import com.ease.aa.system.exception.impl.ExceptionMessageHelper;
import com.ease.aa.system.utility.impl.ResourceLoadHelper;
import com.ease.context.i18n.ResourceRegister.PropertiesCache;
import com.ease.context.i18n.ResourceRegister.ResourceCache;

/**
 * 国际化资源信息取得工具类
 *
 * @author nathanleewei
 */

public class ResourceMessageUtil {

	public static final Locale EOS_DEFAULT_LOCALE = new Locale("EOS_DEFAULT");

	private static final String RESOURCE_EXCEPITON_MAP_FILE_NAME = "META-INF/com.primeton.ext.international.resource.exception";

	// 注册EOS系统的资源文件
	static {

		// 注册Exception资源文件
		Enumeration<URL> resoureceUrl = null;
		try {
			// 搜索Exception资源文件
			resoureceUrl = ResourceMessageUtil.class.getClassLoader().getResources(RESOURCE_EXCEPITON_MAP_FILE_NAME);
		} catch (IOException ignore) {
			// log.warn("Search [resource={0}] error!", new
			// Object[]{RESOURCE_EXCEPITON_MAP_FILE_NAME}, ignore);
		}

		// 解析文件
		if (resoureceUrl != null) {
			while (resoureceUrl.hasMoreElements()) {
				Properties resourceProp = new Properties();
				InputStream stream = null;
				URL exceptionResourceUrl = resoureceUrl.nextElement();
				try {
					stream = exceptionResourceUrl.openStream();
					resourceProp.load(stream);
				} catch (IOException ignore) {
					// log.warn("Load [resource={0}] error!", new
					// Object[]{exceptionResourceUrl.getFile()}, ignore);
				} finally {
					try {
						if (stream != null) {
							stream.close();
						}
					} catch (IOException ignore) {

					}
				}

				// 注册Exception资源文件
				for (Entry<?, ?> entry : resourceProp.entrySet()) {
					String resource = String.valueOf(entry.getKey()) + String.valueOf(entry.getValue());
					Locale locale = ResourceLoadHelper.getResourceLoacle(resource);
					ResourceCache.SYS_RESOURCE.registerResource(ResourceRegister.EXCEPTION, locale, resource);
					PropertiesCache.SYS_PROPERTY.put(ResourceRegister.EXCEPTION, locale, ResourceLoadHelper.loadResourceProperties(resource));
				}
			}
		}
	}

	/**
	 * 取得异常的message
	 *
	 * @param message_id
	 *            信息编号
	 * @return 异常message
	 */
	public static String getExceptionResourceMessage(String message_id) {
		return getExceptionResourceMessage(message_id, Locale.getDefault());
	}

	/**
	 * 取得异常的message
	 *
	 * @param message_id
	 *            信息编号
	 * @param locale
	 *            国际位置
	 * @return 异常message
	 */
	public static String getExceptionResourceMessage(String message_id, Locale locale) {
		return getResourceMessage(ResourceRegister.EXCEPTION, message_id, locale);
	}

	/**
	 * 取得I18n的message
	 *
	 * @param message_id
	 *            信息编号
	 * @return I18n message
	 */
	public static String getI18nResourceMessage(String message_id) {
		return getI18nResourceMessage(message_id, Locale.getDefault());
	}

	/**
	 * 取得I18n的message
	 *
	 * @param message_id
	 *            信息编号
	 * @param locale
	 *            国际位置
	 * @return I18n message
	 */
	public static String getI18nResourceMessage(String message_id, Locale locale) {
		return getResourceMessage(ResourceRegister.I18N, message_id, locale);
	}

	/**
	 * 取得message
	 *
	 * @param resourceType
	 *            资源类型
	 * @param message_id
	 *            信息编号
	 * @param locale
	 *            国际位置
	 * @param defaultValue
	 *            默认值
	 * @return message
	 */
	public static String getResourceMessage(String resourceType, String message_id, Locale locale, String defaultValue) {
		String message = getResourceMessage(resourceType, message_id, locale);
		return message == null ? defaultValue : message;
	}

	/**
	 * 取得message
	 *
	 * @param resourceType
	 *            资源类型
	 * @param message_id
	 *            信息编号
	 * @param locale
	 *            国际位置
	 * @return message
	 */
	public static String getResourceMessage(String resourceType, String message_id, Locale locale) {
		if (message_id == null) {
			return null;
		}

		// 先搜索EOS系统资源
		Properties prop = autoSearchProperties(PropertiesCache.SYS_PROPERTY, ResourceCache.SYS_RESOURCE, resourceType, locale, true);
		String message = prop.getProperty(message_id);
		// 如果EOS系统中message不存在
		if (message == null) {
			// 搜索用户资源
			prop = autoSearchProperties(PropertiesCache.USER_PROPERTY, ResourceCache.USER_RESOURCE, resourceType, locale, true);
			message = prop.getProperty(message_id);
			// 如果相应的国际化message不存在,取默认的国际化
			if (message == null) {
				prop = PropertiesCache.SYS_PROPERTY.get(resourceType, EOS_DEFAULT_LOCALE);
				message = prop.getProperty(message_id);
				// 如果EOS系统默认的国际化message不存在
				if (message == null) {
					prop = PropertiesCache.USER_PROPERTY.get(resourceType, EOS_DEFAULT_LOCALE);

					message = prop.getProperty(message_id);
					if (message == null) {
						// 最后搜索类路径中META-INF/resources/ExceptionResource_XXX.
						// properties资源文件
						message = ExceptionMessageHelper.getMessage(message_id, locale);
					}
				}
			} else {
				return message;
			}
		} else {
			return message;
		}

		return message;
	}

	private static Map<Locale, Object> lockMap = new HashMap<Locale, Object>();

	private static synchronized Object getLock(Locale locale) {
		Object lock = lockMap.get(locale);
		if (lock == null) {
			lock = new Object();
			lockMap.put(locale, lock);
		}
		return lock;
	}

	// 查找Locale所对应的国际化资源,注意：只查找一次
	private static Properties autoSearchProperties(PropertiesCache propertyCache, ResourceCache resourceCache, String resourceType, Locale locale, boolean isOnlyOnce) {
		Properties propLocale = propertyCache.get(resourceType, locale);
		// 不存在就自动查找
		if (propLocale == null || (!isOnlyOnce && propLocale.isEmpty())) {
			// 并发控制
			Object lock = getLock(locale);
			synchronized (lock) {
				propLocale = propertyCache.get(resourceType, locale);
				if (propLocale == null || (!isOnlyOnce && propLocale.isEmpty())) {
					registerLocalePropperties(propertyCache, resourceCache, resourceType, locale);
					propLocale = propertyCache.get(resourceType, locale);
					if (propLocale == null) {
						propLocale = new Properties();
						// 只查找一次
						if (isOnlyOnce) {
							propertyCache.put(resourceType, locale, propLocale);
						}
					}
				}
			}
		}
		return propLocale;
	}

	// 注册国际化资源
	private static void registerLocalePropperties(PropertiesCache propertyCache, ResourceCache resourceCache, String resourceType, Locale locale) {
		// 以默认国际化资源文件为基准搜索locale国际化文件
		String[] resoureFiles = resourceCache.getResourceFileNames(resourceType, EOS_DEFAULT_LOCALE);
		for (String resource : resoureFiles) {
			int index = resource.lastIndexOf('.');
			String localFileName = resource;
			String extention = "";
			// 分割文件扩展名
			if (index != -1) {
				localFileName = resource.substring(0, index);
				extention = resource.substring(index);
			}
			localFileName =(localFileName+ "_"+ locale.toString()+extention);
			Properties prop = ResourceLoadHelper.loadResourceProperties(localFileName);
			if (!prop.isEmpty()) {
				resourceCache.registerResource(resourceType, locale, localFileName);
				propertyCache.put(resourceType, locale, prop);
			}
		}
	}
}
/*
 * 修改历史 $Log: ResourceMessageUtil.java,v $ 修改历史 Revision 1.1 2012/09/26 16:17:27 liwei 修改历史 init 修改历史 修改历史 Revision 1.1
 * 2012/09/09 10:16:53 liwei 修改历史 init 修改历史 修改历史 Revision 1.1 2012/09/09 09:32:25 liwei 修改历史 init 修改历史 修改历史 Revision 1.1
 * 2012/09/07 05:52:00 liwei 修改历史 init 修改历史 修改历史 Revision 1.1 2012/05/30 09:56:33 liwei 修改历史 *** empty log message ***
 * 修改历史 修改历史 Revision 1.3 2012/03/19 17:42:30 liwei 修改历史 init 修改历史 修改历史 Revision 1.2 2012/03/13 20:24:08 liwei 修改历史 init
 * 修改历史 修改历史 Revision 1.1 2012/03/13 17:17:04 liwei 修改历史 init 修改历史 修改历史 Revision 1.2 2012/03/01 06:28:11 liwei 修改历史 init
 * 修改历史 修改历史 Revision 1.1 2012/02/28 07:13:16 liwei 修改历史 init 修改历史 Revision 1.2 2011/08/19 08:37:29 chengy Add:
 * 增加先从类路径的META-INF/resources/ExceptionResource_xxx.properties加载异常的资源文件能力
 *
 * Revision 1.1 2011/06/02 09:23:24 wangfeng 迁移项目
 *
 * Revision 1.3 2011/02/25 08:46:37 litw Update：修改资源判空返回
 *
 * Revision 1.2 2010/06/01 02:34:14 wuyh Update:增加默认值接口
 *
 * Revision 1.1 2010/01/26 01:35:29 wanglei Add:迁移6.1CVS到6.2CVS上
 *
 * Revision 1.1 2009/11/18 07:11:15 wanglei Add:提交到CVS。
 *
 * Revision 1.8 2008/10/15 07:01:21 wuyh BUG:12992
 * 基础构件库的com.eos.foundation.eoscommon.ResourcesMessageUtil类的四个构件都没处理空key的情况
 *
 * Revision 1.7 2008/08/11 09:08:19 wangfeng Bug：11398[wuyh]国际化资源自动搜索功能没有并发控制
 *
 * Revision 1.6 2008/08/05 07:43:10 wangcq BUG: 11105 异常资源加载不完整,中文部分不能加载
 *
 * Revision 1.5 2008/07/28 03:21:32 wangcq JIRA：EOS-2480 国际化资源自动搜索功
 *
 * Revision 1.4 2008/07/24 08:02:11 wangcq BUG：10521 EOS异常国际化资源文件加载有问题
 *
 * Revision 1.3 2008/07/23 06:12:43 wuyh BUG:10440 异常资源文件加载不成功
 *
 * Revision 1.2 2008/07/11 06:24:15 wuyh CodeReview:修改关闭输入流的null判断
 *
 * Revision 1.1 2008/07/04 11:55:14 build Added by Needle,Sxn,Sccot
 *
 * Revision 1.3 2008/06/24 07:34:57 wuyh BUG:9680 异常信息国际化的时候,如果我的message没有在property里面定义,会导致重新加载所有的国际化信息文件
 *
 * Revision 1.2 2008/06/02 05:28:42 wuyh BUG： 9148 加载异常、国际化文件可能存在风险
 *
 * Revision 1.1 2008/05/07 09:03:31 wuyh JIRA：EOS-1056 ,异常处理需要统一考虑国际化等特殊问题
 *
 * Revision 1.3 2008/05/06 09:00:21 wuyh JIRA：EOS-1056 ,异常处理需要统一考虑国际化等特殊问题
 *
 * Revision 1.2 2008/05/06 05:35:20 wuyh JIRA：EOS-1056 ,异常处理需要统一考虑国际化等特殊问题
 *
 * Revision 1.1 2007/12/24 09:09:08 wuyh Update:国际化资源注册移动到通用工具模块
 */